<?php
/**
 * | 节程 [ 节程赋能开发者，助力企业发展 ]
 * +----------------------------------------------------------------------
 *  | Copyright (c) 2020~2029 温州惊蛰网络科技有限公司 All rights reserved.
 * +----------------------------------------------------------------------
 *  | Licensed 节程并不是自由软件，未经许可不能去掉节程相关版权
 * +----------------------------------------------------------------------
 */
declare (strict_types=1);

namespace app\command;

use app\utils\Receipts;
use think\console\Command;
use think\console\Input;
use think\console\Output;
use think\db\exception\DbException;
use think\Exception;
use think\exception\ErrorException;
use think\facade\Db;

class Receiving extends BaseCommand
{
    private $order_id = [];
    private $orders = [];

    protected function configure()
    {
        // 指令配置
        $this->setName('receiving')
            ->setDescription('自动收货,自动评论');
    }

    protected function execute(Input $input, Output $output)
    {

        $this->setDb($input, $output);
    }


    private function option(): void
    {
        try {
            $a = $b = $c = $d = $f = $e = [];
            $receipts = new Receipts();
            $orders = $this->getOrders();
            $order_commodity = $this->getOrderCommodity();
            $merchant = $this->getMerchant();
            $task = $this->getReceiptsTask();
            $template = $this->getTemplate();
            $printer = $this->getPrinter();
            $user = $this->getUser();
            $task = $this->setTask($task, $template, $printer);
            $b = $this->array_function($merchant);
            $c = $this->array_function($user);
            foreach ($order_commodity as $key => $value) {
                $f = $value;
                $d[$value['order_id']][] = array2object($f);
                if (!empty($value['sku_id']))
                    $a[$value['order_id']][$value['commodity_id']][$value['sku_id']] = $value['id'];
                else
                    $a[$value['order_id']][$value['commodity_id']][0] = $value['id'];
            }
            foreach ($orders as $index => $order) {
                $this->order_funtion($order);
                $e = $order;
                $e['user'] = array2object($c[$order['user_id']]);
                $e['order_commodity'] = array2object($d[$order['id']]);
                $e = array2object($e);
                foreach ($task as $key => $item) {
                    $value = array2object($item);
                    $receipts->setMerchant($b[$order['merchant_id']])
                        ->setOrderData($e)
                        ->setTemplate($value->template)
                        ->setPrinter($value->printer)
                        ->implementationPlan($value->number);
                }
            }
        } catch (Exception $exception) {
            echo $exception->getMessage() . '[' . $exception->getTraceAsString() . ']';
        }
    }


    public function deliver(array $data)
    {
        try {
            Db::name('order_commodity')->where(['id' => $data['id']])->update(['status' => 7,'receiving_time' => date('Y-m-d H:i:s')]);
            $this->upOrderState($data['order_id']);
            $this->order_id[] = $data['order_id'];
        } catch (ErrorException $errorException) {
            echo $errorException->getMessage();
        }
    }


    public function opinion(array $data)
    {
        try {
            Db::name('order_commodity')->where(['id' => $data['id']])->update(['status' => 5]);
            $find = Db::name('order_commodity')
                ->alias('a')
                ->join('order o', 'o.id = a.order_id', 'LEFT')
                ->field('o.user_id,a.order_id,a.commodity_id,IFNULL(a.sku_id,null) as sku_id,o.mall_id')
                ->find($data['id']);

            Db::name('order_evaluate')
                ->insert([
                    'user_id' => $find['user_id'],
                    'mall_id' => $find['mall_id'],
                    'order_id' => $find['order_id'],
                    'commodity_id' => $find['commodity_id'],
                    'content' => "默认好评!",
                    'state' => 2,
                    'sku' => $find['sku_id'],
                    'create_time' => date("Y-m-d H:i:s", time())
                ]);
            $this->upOrderState($data['order_id']);
        } catch (DbException $e) {
            echo $e->getMessage();
        }
    }

    private function upOrderState($oId)
    {
        try {
            //订单状态: 1-待支付 2-待发货 3-已发货 4-已完结 5-已评价 6-删除 7-部分发货 8-已收货 9-部分收货 10-维权中 11-维权完成 12-已关闭
            //订单-商品状态: 1-待支付 2-待发货 3-已发货 4-已完结 5-已评价 6-删除 7-已收货 8-维权中 9-已维权 10-维权驳回 11-已关闭
            $status_arr = Db::name('order_commodity')->where('order_id', $oId)->field('status')->group('status')->select()->toArray();
            $status = array_column($status_arr, 'status');
            if (count($status) > 1) {
                foreach ($status as $k => $v) {
                    if ($v == 11) unset($status[$k]);
                }
                if (in_array(3, $status) && count($status) > 1 && !in_array(2, $status))
                    $state = 7;
                elseif (in_array(2, $status) && count($status) > 1)
                    $state = 2;
                elseif (in_array(7, $status) && count($status) > 1)
                    $state = 9;
                elseif (count($status) == 1)
                    $state = in_array(end($status), [7]) ? end($status) + 1 : end($status);
            } elseif (count($status) == 1) {
                switch ($status[0]) {
                    case 2:
                        $state = 2;
                        break;
                    case 3:
                        $state = 3;
                        break;
                    case 4:
                        $state = 4;
                        break;
                    case 5:
                        $state = 5;
                        break;
                    case 6:
                        $state = 6;
                        break;
                    case 7:
                        $state = 8;
                        break;
                    case 11:
                        $state = 12;
                        break;
                }
            }
            Db::name('order')->where('id', $oId)->update(['status' => $state]);
        } catch (DbException $e) {
            echo $e->getMessage();
        }
    }


    private function order_funtion(array $order): void
    {
        $order_id = array_column($order, 'id');
        Db::name('agent_bill_temporary')
            ->where('order_id', 'IN', $order_id)
            ->update(['update_time' => date('Y-m-d H:i:s')]);
    }


    private function getOrders(): array
    {
        $this->order_id = array_unique($this->order_id);
        $this->orders = Db::name('order')
            ->where('id', 'IN', $this->order_id)
            ->select()
            ->toArray();
        return $this->orders;
    }


    private function getOrderCommodity(): array
    {
        $in = array_column($this->orders, 'id');
        $in = array_unique($in);
        return Db::name('order_commodity')
            ->field('o.id,o.money AS price,order_id,commodity_id,o.count,o.receiving_time,o.money,o.order_id,o.sku_id,(CASE WHEN o.sku_id IS NULL THEN c.name ELSE CONCAT(c.name,\'(\',(select pvs_value FROM jiecheng_sku WHERE id=o.sku_id),\')\') END) AS name,`group`')
            ->alias('o')
            ->join('commodity c', 'c.id=o.commodity_id', 'left')
            ->where('o.order_id', 'IN', $in)
            ->where('o.status', 7)
            ->select()
            ->toArray();
    }


    private function getUser(): array
    {
        $in = array_column($this->orders, 'user_id');
        return Db::name('user')
            ->field('id,nickname,name,mobile')
            ->where('id', 'IN', $in)
            ->select()
            ->toArray();
    }


    private function getMerchant(): array
    {
        $in = array_column($this->orders, 'merchant_id');
        $in = array_unique($in);
        return Db::name('merchant')
            ->where('id', 'IN', $in)
            ->select()
            ->toArray();
    }

    private function getReceiptsTask(): array
    {
        return Db::name('receipts_task')
            ->where('delete_time', 'NULL')
            ->select()
            ->toArray();
    }

    private function getTemplate(): array
    {
        return Db::name('receipts_template')
            ->where('delete_time', 'NULL')
            ->select()
            ->toArray();
    }


    private function getPrinter(): array
    {
        return Db::name('receipts_printer')
            ->where('delete_time', 'NULL')
            ->select()
            ->toArray();
    }

    private function setTask(array $task, array $template, array $printer): array
    {
        $c = $a = $b = [];
        $a = $this->array_function($template);
        $b = $this->array_function($printer);
        foreach ($task as $key => $value) {
            $configure = json_decode($value['configure']);
            if (empty($configure->receiving)) continue;
            $c[$key] = $value;
            $c[$key]['configure'] = $configure;
            $c[$key]['template'] = $a[$value['template_id']];
            $c[$key]['printer'] = $b[$value['printer_id']];
        }
        return $c;
    }

    private function array_function(array $array, string $key = 'id'): array
    {
        $arr = [];
        foreach ($array as $index => $value) {
            $arr[$value[$key]] = $value;
        }
        return $arr;
    }

    protected function executeAction(Input $input, Output $output)
    {
        $this->redis = new \app\utils\RedisUtil();

        $config = Db::name('configuration')
            ->field('mall_id,configuration')
            ->where('type', 'tradeSetting')
            ->select()
            ->toArray();
        foreach ($config as $key => $value) {
            $js = json_decode($value['configuration'], true);
            if (!$js['is_auto_receiving']) continue;
            $where[] = !($js['order_evaluate']) ? ['status', 'IN', [3]] : ['status', 'IN', [3, 7]];
            $where[] = ['after_status', '=', 3];
            $res = Db::name('order_commodity')
                ->where($where)
                ->where('mall_id', $value['mall_id'])
                ->whereTime('deliver_time|receiving_time', '<', '-' . $js['receiving_time'] . ' day')
                ->select()
                ->toArray();
            foreach ($res as $v) {
                if ($v['status'] == 3) {
                    $this->deliver($v);
                } elseif ($v['status'] == 7) {
                    $this->opinion($v);
                }
            }
            if (!empty($this->order_id)) $this->option();
        }
        // 指令输出
        $output->writeln('receiving');
    }
}
